package net.tavion.angelboot.framework.logger;

import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.lang3.StringUtils;

import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Log desensitization output
 * Only valid for json output
 * @author liu_chang
 * @date 2018-08-24 11:03
 */
public class MaskingPatternLayout extends PatternLayout {
    private String patternsProperty;
    private Optional<Pattern> pattern;
    /**
     * Maximum length of desensitized content that can be processed
     */
    private static final  int  MAX_DEAL_LENGTH=100;

    private static final  char JSON_CHARGE_CHAR='"';
    private static final   char JSON_CHARGE_CHAR2=':';

    public String getPatternsProperty() {
        return patternsProperty;
    }

    public void setPatternsProperty(String patternsProperty) {
        this.patternsProperty = patternsProperty;
        if (this.patternsProperty != null) {
            this.pattern = Optional.of(Pattern.compile(patternsProperty, Pattern.MULTILINE));
        } else {
            this.pattern = Optional.empty();
        }
    }

    /**
     * Once the keyword is matched, determine whether it is followed by a double quotation mark,
     * thereby estimating whether it is json, and replace its contents
     * @param event
     * @return
     */
    @Override
    public String doLayout(ILoggingEvent event) {
        final StringBuilder message = new StringBuilder(super.doLayout(event));
        int length=message.length();
        if (pattern.isPresent()) {
            Matcher matcher = pattern.get().matcher(message);
            while (matcher.find()) {
                int group = 1;
                while (group <= matcher.groupCount()) {
                    if (matcher.group(group) != null) {
                        int matcherEnd=matcher.end(group);
                        int jsonChargeIndex=matcherEnd+2;
                        if( length>=jsonChargeIndex){
                            char chargeChar=message.charAt(jsonChargeIndex);
                            if(JSON_CHARGE_CHAR==chargeChar){
                                //Whether the estimate is json or not
                                int searchCharIndex=matcherEnd+3;
                                if(length<searchCharIndex){
                                    break;
                                }
                                int nextChar=message.indexOf(JSON_CHARGE_CHAR+"",searchCharIndex);
                                if(nextChar-searchCharIndex>MAX_DEAL_LENGTH||nextChar-searchCharIndex==0){
                                    break;
                                }
                                String padStr= StringUtils.leftPad("*",nextChar-(jsonChargeIndex+1),"*");
                                message.replace(jsonChargeIndex+1,nextChar,padStr);
                            }else if(JSON_CHARGE_CHAR2==chargeChar){
                                //Item: audio file with audio file format {\"address\":\" China \"}
                                int searchCharIndex=matcherEnd+5;
                                if(length<searchCharIndex){
                                    break;
                                }
                                int nextChar=message.indexOf(JSON_CHARGE_CHAR+"",searchCharIndex);
                                if(nextChar-searchCharIndex>MAX_DEAL_LENGTH||nextChar-searchCharIndex==1){
                                    break;
                                }
                                String padStr= StringUtils.leftPad("*",nextChar-(jsonChargeIndex+4),"*");
                                message.replace(jsonChargeIndex+3,nextChar-1,padStr);
                            }
                        }
                    }
                    group++;
                }
            }
        }
        return message.toString();
    }

}

